package sw6.admin;

import sw6.admin.database.DatabaseHelper;
import sw6.lib.internal.PrivateDefinitions;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;

/**
 * This class has the purpose to make an interface to the sw6.admin database.
 * The interface is not made to let the users make to be used directly as a 
 * general content provider but rather should be used using the methods in the
 * sw6.lib.Settings class.
 * <br><br>
 * The class is defined as a content provider which means that other processes 
 * and activities on the system can call our class. The idea is you can 
 * query and update variables from the database inside sw6.admin from commands
 * there are defined in the sw6.lib.
 * <br><br>
 * The figure below illustrate an example where an application wants to get an 
 * integer and call therefore the getInteger() method in sw6.lib (the program 
 * has already included the sw6.lib). Sw6.lib is made to uses the 
 * ContentProvider sw6.admin.SettingsProvider to query information about 
 * different variables. Since SettingProvider is a content provider, it will 
 * run under the same rights as the rest of the sw6.admin program and have 
 * access to any data belonging sw6.admin. Since the database is part of 
 * sw6.admin, we can get our integer from the database and send the value all 
 * the way back to the program who asked about it.
 * 
 * <pre>
 * {@code
 * [Process of getting an Integer from the database]
 *                                                            sw6.admin       
 *                                                      |--------------------|
 *                                                      |  Settingsprovider  |
 * |---------|   getInteger()   |---------|   query()   | |----------------| |
 * | Program |  ------------->  | sw6.lib |  -------->  | | DatabaseHelper | |  
 * |---------|  <-------------  |---------|  <--------  | |----------------| |
 *              (Return value)                (result)  |--------------------|
 * }</pre>
 * 
 * @author sw6b
 */
public class SettingsProvider extends ContentProvider {
	
	private static final UriMatcher URI_MATCHER;
	private static final int MATCH_OBJECT			= 1;
	private static final int MATCH_BOOLEAN			= 2;
	private static final int MATCH_INTEGER			= 3;
	private static final int MATCH_DOUBLE			= 4;
	private static final int MATCH_STRING			= 5;
	private static final int MATCH_ENUM				= 6;
//	private static final int MATCH_ENUM_ELEMENT		= 7;
	
	// Removed support for insert data because we don't need this 'feature'. For more information look in the insert() method.
//	private static final int MATCH_INSERT_INTEGER	= 8;
//	private static final int MATCH_INSERT_DOUBLE	= 9;
//	private static final int MATCH_INSERT_STRING	= 10;
	
	private DatabaseHelper dbHelper;
	
	static {
		// content://sw6.admin.settingsprovider/TYPE/APP_NAME/VAR_NAME/
		URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
		URI_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.OBJECT			+ "/*/*/*", MATCH_OBJECT);
		URI_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.BOOLEAN		+ "/*/*", 	MATCH_BOOLEAN);
		URI_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.INTEGER		+ "/*/*", 	MATCH_INTEGER);
		URI_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.DOUBLE			+ "/*/*", 	MATCH_DOUBLE);
		URI_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.STRING			+ "/*/*",	MATCH_STRING);
		URI_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.ENUM			+ "/*/*",	MATCH_ENUM);
//		URL_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.ENUM_ELEMENT	+ "/*/*",	MATCH_ENUM_ELEMENT);
		
		// Removed support for insert data because we don't need this 'feature'. For more information look in the insert() method.
//		URL_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.INTEGER		+ "/*/*/*/*", 	MATCH_INSERT_INTEGER);
//		URL_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.DOUBLE			+ "/*/*/*/*", 	MATCH_INSERT_DOUBLE);
//		URL_MATCHER.addURI(PrivateDefinitions.PROVIDER_CLASS, PrivateDefinitions.STRING			+ "/*/*/*/*",	MATCH_INSERT_STRING);
	}
	
	@Override
	public boolean onCreate() {
		dbHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public String getType(Uri uri) {
		/*
		 *  We don't need to provide this "service" because 
		 *  we are makring our own implementation (sw6.lib.Settings) 
		 *  to communicate with this content provider.
		 */
		return null;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		Cursor resultCursor = null;
		int match = URI_MATCHER.match(uri);

		if (match != -1) {
			String appName	= uri.getPathSegments().get(1);
			String varName	= uri.getPathSegments().get(2);
			
			switch (match) {
				case MATCH_ENUM:
					resultCursor = dbHelper.getEnum(appName, varName);
					break;
				case MATCH_OBJECT:
					String varCanonicalClassName = uri.getPathSegments().get(3);
					resultCursor = dbHelper.getObject(appName, varName, varCanonicalClassName);
					break;
				case MATCH_BOOLEAN:
					resultCursor = dbHelper.getBoolean(appName, varName);
					break;
				case MATCH_INTEGER:
					resultCursor = dbHelper.getInteger(appName, varName);
					break;
				case MATCH_DOUBLE:
					resultCursor = dbHelper.getDouble(appName, varName);
					break;
				case MATCH_STRING:
					resultCursor = dbHelper.getString(appName, varName);
					break;
				default:
					return null;
			}
			resultCursor.setNotificationUri(getContext().getContentResolver(), uri);
		}
		return resultCursor;
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		/*
		 * This code is disabled since we no longer need to insert new 
		 * variables in the database by using the SettingsProvider. The 
		 * reason is that we now use the different programs settings.xml 
		 * file to determine which variables who are in the database and 
		 * this file is checked when the program is installed. So it is 
		 * no longer necessary to the programs themselves insert 
		 * variables into the database.
		 */
//		int match = URL_MATCHER.match(uri);
//
//		if (match != -1) {
//			String appName	= uri.getPathSegments().get(1);
//			String varName	= uri.getPathSegments().get(2);
//			int minInt = 0;
//			int maxInt = 0;
//			double minDouble = 0.0;
//			double maxDouble = 0.0;
//			switch (match) {
//				case MATCH_ENUM:
//					dbHelper.insertEnum(appName, varName, values.getAsInteger(PrivateDefinitions.VAR_VALUE));
//					break;
//				case MATCH_ENUM_ELEMENT:
//					dbHelper.insertEnumElement(appName, varName, values.getAsInteger(PrivateDefinitions.VAR_VALUE));
//					break;
//				case MATCH_OBJECT:
//					String varCanonicalClassName = uri.getPathSegments().get(3);
//					dbHelper.insertObject(appName, varName, varCanonicalClassName, values.getAsByteArray(PrivateDefinitions.VAR_VALUE));
//					break;
//				case MATCH_BOOLEAN:
//					dbHelper.insertBoolean(appName, varName, values.getAsBoolean(PrivateDefinitions.VAR_VALUE));
//					break;
//				case MATCH_INSERT_INTEGER:
//					minInt = Integer.parseInt(uri.getPathSegments().get(3));
//					maxInt = Integer.parseInt(uri.getPathSegments().get(4));
//					dbHelper.insertInteger(appName, varName, values.getAsInteger(PrivateDefinitions.VAR_VALUE), minInt, maxInt);
//					break;
//				case MATCH_INSERT_DOUBLE:
//					minDouble = Double.parseDouble(uri.getPathSegments().get(3));
//					maxDouble = Double.parseDouble(uri.getPathSegments().get(4));
//					dbHelper.insertDouble(appName, varName, values.getAsDouble(PrivateDefinitions.VAR_VALUE), minDouble, maxDouble);
//					break;
//				case MATCH_INSERT_STRING:
//					minInt = Integer.parseInt(uri.getPathSegments().get(3));
//					maxInt = Integer.parseInt(uri.getPathSegments().get(4));
//					dbHelper.insertString(appName, varName, values.getAsString(PrivateDefinitions.VAR_VALUE), minInt, maxInt);
//					break;
//				default:
//					return null;
//			}
//			getContext().getContentResolver().notifyChange(uri, null);
//			return uri;
//		}
//		return null;
		
		// We return always null because we never insert any data
		return null;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		int returnValue = 0;
		int match = URI_MATCHER.match(uri);

		if (match != -1) {
			String appName	= uri.getPathSegments().get(1);
			String varName	= uri.getPathSegments().get(2);
			switch (match) {
				case MATCH_ENUM:
					returnValue = dbHelper.updateEnum(appName, varName, values.getAsInteger(PrivateDefinitions.VAR_VALUE));
					break;
				case MATCH_OBJECT:
					String varCanonicalClassName = uri.getPathSegments().get(3);
					returnValue = dbHelper.updateObject(appName, varName, varCanonicalClassName, values.getAsByteArray(PrivateDefinitions.VAR_VALUE));
					break;
				case MATCH_BOOLEAN:
					returnValue = dbHelper.updateBoolean(appName, varName, values.getAsBoolean(PrivateDefinitions.VAR_VALUE));
					break;
				case MATCH_INTEGER:
					returnValue = dbHelper.updateInteger(appName, varName, values.getAsInteger(PrivateDefinitions.VAR_VALUE));
					break;
				case MATCH_DOUBLE:
					returnValue = dbHelper.updateDouble(appName, varName, values.getAsDouble(PrivateDefinitions.VAR_VALUE));
					break;
				case MATCH_STRING:
					returnValue = dbHelper.updateString(appName, varName, values.getAsString(PrivateDefinitions.VAR_VALUE));
					break;
				default:
					return 0;
			}
			getContext().getContentResolver().notifyChange(uri, null);
		}
		return returnValue;
	}
	
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		return 0;
	}

}
